package com.chunguang.netty.comon;

import java.util.concurrent.TimeUnit;

import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.chunguang.netty.domain.RequestData;
import com.chunguang.netty.domain.TransferData;
import com.chunguang.netty.listener.ApplicationFactory;
import com.chunguang.netty.service.RequestDataService;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.ReadTimeoutHandler;

public class Client {
	
	private static class SingletonHolder {
		static final Client instance = new Client();
	}
	
	public static Client getInstance(){
		return SingletonHolder.instance;
	}
	
	private EventLoopGroup group;
	private Bootstrap b;
	private ChannelFuture cf ;
	private Client(){
			group = new NioEventLoopGroup();
			b = new Bootstrap();
			b.group(group)
			 .channel(NioSocketChannel.class)
			 .handler(new ChannelInitializer<SocketChannel>() {
					@Override
					protected void initChannel(SocketChannel sc) throws Exception {
						sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
						sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
						sc.pipeline().addLast(new ReadTimeoutHandler(60));
						sc.pipeline().addLast(new ClientHandler());
					}
		    });
	}
	
	public void connect(){
		try {
			this.cf = b.connect("127.0.0.1", 8765).sync();
			System.out.println("远程服务器已经连接, 可以进行数据交换..");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}  
	}
	
	public ChannelFuture getChannelFuture(){
		if(this.cf == null) {
			this.connect();
		}
		if(!this.cf.channel().isActive()){
			this.connect();
		}
		return this.cf;
	}
	
	public void close(){
		try {
			this.cf.channel().closeFuture().sync();
			this.group.shutdownGracefully();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
//		如果是springweb项目中进行数据同步，这里需要在监听器中进行创建实例
		
//     然后再service 获取futurechannle进行发送数据，
		
//		然后再spring工厂销毁 的方法中中进行 close    
		
		
//		如果在非web项目中，应该先创 启动一个channel组，然后进行用一个线程永不退出去执行推送数据。 
		
		
		/**
		 *     
		 *     
		 *     如果是单线程的话，就只要 一个线程 进行await就行了。
		 *     await 和wait需要被唤醒，不然就报错
		 *     如果是需要多个线程的话，就可以
		 *     
		 *     
		 *     另外重点强调的一点就是：  client  只有两种状态，    1， 连接  
		 *     												   2， 断开连接后， netty就自动结束了，如果没有线程阻塞保持者
		 *     												以便于下次在此或得连接的时候，就是结束，否则的话，就是可以进行重连的。
		 *     												所以我们只要保持一个线程可以进行重连就行了.
		 */
		
		
		
		final Client client = Client.getInstance();
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( new String[] { "spring-context.xml" });
		context.start();
		new Thread(new Runnable() {
			int i = 0;
			@Override
			public void run() {
				while(true){
					ChannelFuture channelFuture = client.getChannelFuture();
					ApplicationContext context1 = ApplicationFactory.getContext();
					System.out.println("dddddddd");
					RequestDataService service = (RequestDataService) context1.getBean("requestDataService");
					TransferData transferData = new TransferData();
					transferData.setCheckNumber("aaaaaaaaaaeeaaaagggddddaaaa"+ i++);
					transferData.setSync(0);
					service.insert(transferData );
					RequestData requestData2 = new RequestData();
					BeanUtils.copyProperties(transferData, requestData2, new String[]{"sync"});
					channelFuture.channel().writeAndFlush(requestData2);
					
					try {
						TimeUnit.SECONDS.sleep(5);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					
					
					
				}
				
			}
		}).start();
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
	}
}
